package com.lenovo.leos.letools.lenovodata;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.lenovo.leos.letools.db.AllUploadTaskEntity;
import com.lenovo.leos.letools.db.FileUploadEntity;
import com.lenovo.leos.letools.db.FileUploadService;
import com.lenovo.leos.letools.domain.Folder;
import com.lenovo.leos.letools.exception.NetException;
import com.lenovo.leos.letools.exception.PreUploadException;
import com.lenovo.leos.letools.interaces.DownloadProgressListener;
import com.lenovo.leos.letools.lenovodata.DownLoadServer.TotalFilelenPreDir;
import com.lenovo.leos.letools.utils.JSONParser;

public class UploadServer {

	private Context context;
	// key 要上传文件的全路径 ；value开启的上传线程
	private Map<String, UploadThread> uploadThreads;
	//文件夹上传用到  key 要上传文件夹的全路径 ；value这个文件夹下的所有文件开启的上传线程集合
	private Map<String, List<UploadThread>> dirUploadThreads;
	private FileUploadService fileUploadService;
	private BaseNetClientServer baseClient;
	private static UploadServer instance;

	private UploadServer(Context context) {
		this.context = context;
		uploadThreads = new HashMap<String, UploadThread>();
		dirUploadThreads = new HashMap<String, List<UploadThread>>();
		fileUploadService = new FileUploadService(context);
		baseClient = new BaseNetClientServer();
	}

	public static UploadServer getInstance(Context context){
		if(null == instance){
			instance = new UploadServer(context);
		}
		return instance;
	}
	/**
	 * 创建一个文件上传任务
	 * @param wholePath 文件路径全称（路径+文件名） 
	 * @param parentDirId 要上传文件到的服务器端的dirid 
	 * @param customFileName 为上传文件自定义的文件名
	 * @param localTopDirWholePath 文件夹上传用到  文件夹的顶层目录全路径 文件上传时  localTopDirWholePath应该为null
	 * @throws NetException 
	 * @throws PreUploadException 文件预上传产生的异常 如-1，-2，-3，-4
	 */
	public void createTask(String wholePath,String parentDirId,String customFileName,String localTopDirWholePath) throws NetException, PreUploadException{
		if(wholePath==null || parentDirId==null) return;
		//得到这个文件
		File file = new File(wholePath);
		String filename = file.getName();
		if(customFileName!=null){
			filename = customFileName;
		}
		//正常返回值中包括上传文件在服务器端生成的id  解析获得这个id值
		Map<String,String> tokenFileidAndURL = baseClient.preupload(context,parentDirId,filename,file.length()+"","1982","1");
		//得到预上传返回的Token值
		String cookie_token = tokenFileidAndURL.get("cookie_token");
		
		String fileid = tokenFileidAndURL.get("fileid");
		String uploadUrl = tokenFileidAndURL.get("uploadUrl");
		//得到这个文件的大小
		int filelen = (int)file.length();
		//文件上传时  localTopDirWholePath应该为null
		fileUploadService.save(wholePath,filelen,fileid,parentDirId,localTopDirWholePath,cookie_token,uploadUrl);
	}
	
	/**
	 * 创建上传文件夹任务
	 * @param dirwholepath
	 * @param parentDirId
	 * @throws NetException 
	 * @throws PreUploadException 
	 */
	public void createDirTask(String dirWholepath,String parentDirId) throws NetException, PreUploadException{
		File[] targetDirs = new File[]{new File(dirWholepath)};
		Map<String,String> fileWholepathMappingParentid = new HashMap<String,String>();
		//将本地文件夹结构，同步到服务器上，同时将"上传本地文件的全路径"和"文件要上传到文件夹id"封装到map中
		recursiveCreateDirAndMapingWholePathAndFileInf(context,targetDirs,parentDirId,fileWholepathMappingParentid);
		for(Map.Entry<String,String> entry:fileWholepathMappingParentid.entrySet()){
			createTask(entry.getKey(),entry.getValue(),null,dirWholepath);
		}
	}
	/**
	 * 将本地文件夹结构，同步到服务器上，同时将"上传本地文件的全路径"和"文件要上传到文件夹id"封装到map中
	 * @param context
	 * @param dirs
	 * @param parentid 此文件夹的父id(在服务器新建文件夹后生成的id)
	 * @param map key为要上传本地文件的全路径   value为文件要上传到文件夹id 
	 * @throws NetException
	 */
	private void recursiveCreateDirAndMapingWholePathAndFileInf(Context context,
			File[] dirs,
			String parentid,
			Map<String,String> map)  throws NetException{
		if(dirs==null) return;
		for(File dir:dirs){
			if(dir.isFile()){
				map.put(dir.getPath(),parentid);
			}
			if(dir.isDirectory()){
				Log.i("dirname","====="+dir.getName());
				String returnVal = baseClient.createDir(context,parentid,dir.getName());
				Folder folder = null;
				try {
					for(int i=0;i<5;i++){
						Log.d("UploadServer","######################## returnVal is:  " + returnVal);
					}
					folder = JSONParser.parseDir(returnVal);//解析创建文件夹操作后返回的值，能获得此文件夹创建后在服务器端生成的id
				} catch (Exception e) {
					e.printStackTrace();
				}
				recursiveCreateDirAndMapingWholePathAndFileInf(context,dir.listFiles(),folder.getId(),map);
			}
		}
	}
	
	/**
	 * 得到所有的上传任务
	 * @return
	 */
	public AllUploadTaskEntity getAllTask(){
		return fileUploadService.getFileAndDirAllTasks();
	}
	/**
	 * 获得一个文件上传任务
	 * @param wholePath
	 * @return
	 */
	public FileUploadEntity getFileTask(String wholePath){
		return fileUploadService.getFileTaskByWholePath(wholePath);
	}
	/**
	 * 获得一个文件夹上传任务
	 * @param localTopDirWholePath
	 * @return
	 */
	public List<FileUploadEntity> getDirTask(String localTopDirWholePath){
		return fileUploadService.getTasksPreTopDirWholePath(localTopDirWholePath);
	}
	/**
	 * 开启一个上传文件线程
	 * 
	 * @param dirid	上传到服务器指定的文件夹id
	 * @param fileNewName  为上传文件起的新文件名
	 * @param wholePath 要上传文件的全路径
	 * @param pb
	 */
	public void startUpload(String wholePath,
			final ProgressBar pb,final TextView tv,int fileLength) {
		FileUploadEntity fue = fileUploadService.getFileTaskByWholePath(wholePath);
		UploadThread upload = null;
		if(null != fue){
			upload = new UploadThread(context,fue,fileLength);
		}
		// 将启动的线程放入线程集合中
		uploadThreads.put(wholePath, upload);
		// 设置回调函数
		if(null != upload){
			upload.setDownloadProgressListener(new DownloadProgressListener() {
				public void onDownloadSize(int size) {
//					pb.setProgress(size);
				}
				public void onDownloadException(int errorStyle) {}
				public void onDownloadOver(String fileid) {}
				public void onDownloadPause(String fileid) {}
				@Override
				public void onChangeDownText(String value) {
//					runOnUi(tv,value);
				}
			});
			//add by gaoge 2011-04-26
			upload.setmProgressBar(pb);
			upload.setTv_percent(tv);
			
			upload.start();
		}
	}
	
	/**
	 * 累加器
	 * 统计文件夹下的所有子文件已经上传了多长的数据 
	 * @author Administrator
	 *
	 */
	public class TotalFilelenPreDir{
		public int mulFileTotalLen=0;
		public DownloadProgressListener downloadProgressListener;
		private ProgressBar dir_mProgressBar;
		private TextView dir_percent;
		
		public TotalFilelenPreDir(int mulFileTotalLen,ProgressBar progressBar,TextView tv){
			this.mulFileTotalLen = mulFileTotalLen;
			this.dir_mProgressBar = progressBar;
			this.dir_percent = tv;
		}
		
		public TotalFilelenPreDir(){
			
		}
		
		public void setDirProgressBar(ProgressBar progressBar){
			this.dir_mProgressBar = progressBar;
		}
		
		public void setDirPercent(TextView tv){
			this.dir_percent = tv;
		}
		
		public ProgressBar getDirProgressBar(){
			return dir_mProgressBar;
		}
		
		public TextView getDirPercent(){
			return dir_percent;
		}
		
		public void setDownloadProgressListener(
				DownloadProgressListener downloadProgressListener) {
			this.downloadProgressListener = downloadProgressListener;
		}
	}
	
	public  TotalFilelenPreDir getNewTotalFilelenPreDir(int mulFileTotalLen,ProgressBar progressBar,TextView tv){
		return new TotalFilelenPreDir(mulFileTotalLen,progressBar,tv);
	}
	/**
	 * 开启一个上传文件夹线程
	 * @param dirWholePath
	 * @param pb
	 */
	public void startDirUpload(String dirWholePath,final ProgressBar pb,final TextView tv,int fileLength){
		List<FileUploadEntity> fues = fileUploadService.getTasksPreTopDirWholePath(dirWholePath);
		List<UploadThread> uts = new ArrayList<UploadThread>();
		
		//here ,because is the upload is first ,we can set the mulFileTotalLen value to 0
		TotalFilelenPreDir tfp = new TotalFilelenPreDir(0,pb,tv);//累加文件夹下所有文件当前上传的长度
		
		tfp.setDownloadProgressListener(new DownloadProgressListener() {
			public void onDownloadSize(int size) {
//				pb.setProgress(size);
			}
			public void onDownloadPause(String fileid) {
			}
			public void onDownloadOver(String fileid) {
			}
			public void onDownloadException(int errorStyle) {
				
			}
			@Override
			public void onChangeDownText(String value) {
				// TODO Auto-generated method stub
//				runOnUi(tv,value);
			}
		});
		for(FileUploadEntity fue : fues){
			
			tfp.mulFileTotalLen+=fue.getStartIndex();//开启上传时 先将保存的断点累加
			
			UploadThread upload = new UploadThread(context,fue,fileLength);
			uts.add(upload);
			upload.setTotalFilelenPreDir(tfp);//将累加器对象传给每个线程
			upload.start();
		}
		//将文件夹上传任务放入  文件夹上传任务集合
		dirUploadThreads.put(dirWholePath,uts);
	}
	/**
	 * 暂停一个文件上传文件线程
	 * 
	 * @param wholePath
	 */
	public void pauseUpload(String wholePath) {
		// 取得对应"文件全路径对应的线程"
		UploadThread ut = uploadThreads.get(wholePath);
		if(ut==null) return;
		ut.setFlag(true);// 暂停这个线程
		uploadThreads.remove(wholePath);
	}
	
	/**
	 * 暂停一个文件夹上传文件线程
	 * 
	 * @param dirWholePath
	 */
	public void pauseDirUpload(String dirWholePath) {
		
		// 取得对应"文件全路径对应的线程"
		List<UploadThread> uts = dirUploadThreads.get(dirWholePath);
		if(uts==null) return;
		for(UploadThread ut : uts){
			if(ut.isAlive()) ut.setFlag(true);// 暂停这个线程
		}
		uts.remove(dirWholePath);//从任务集合中清除这个任务
	}
	
	/**
	 * 得到指定wholePath的任务
	 * @param wholePath
	 * @return
	 */
	public FileUploadEntity getTaskByWholePath(String wholePath){
		return fileUploadService.getFileTaskByWholePath(wholePath);
	}
	/**
	 * 删除一个文件上传任务
	 * @param wholePath
	 */
	public void destoryFileTask(String wholePath){
		this.pauseUpload(wholePath);
		fileUploadService.deleteFileTask(wholePath);
	}
	/**
	 * 删除一个文件夹上传任务
	 * @param wholePath
	 */
	public void destoryDirTask(String localTopDirWholePath){
		this.pauseDirUpload(localTopDirWholePath);
		fileUploadService.deleteDirTask(localTopDirWholePath);
	}
	
	private Handler mHandler = new Handler();
	
	private void runOnUi(final TextView tv,final String value){
		for(int i=0;i<3;i++){
			Log.d("hahaha","runOnUi");
		}
		mHandler.post(new Runnable() {
			@Override
			public void run() {
				tv.setText(value);
			}
		});
	}
	
	//add by gaoge 2011-04-22
	public boolean isUpLoadOver(String strwholepath){
		boolean isLoadOver = false;
		try {
			File file = new File(strwholepath);
			if(file.isFile()){
				for(int i=0;i<20;i++){
					Log.d("downserver","################### strwholepath:" + strwholepath + ",is File");
				}
				FileUploadEntity entity = fileUploadService.getFileTaskByWholePath(strwholepath);
				if(null == entity){
					///数据库里没有该文件的记录，则默认是已经上传完的（前台程序好处理）
					return true;
				}
				isLoadOver = (2 == entity.getFileState());
			}
			else if(file.isDirectory()){
				for(int i=0;i<20;i++){
					Log.d("downserver","################### strwholepath:" + strwholepath + ",is Dir");
				}
				List<FileUploadEntity> entities = fileUploadService.getTasksPreTopDirWholePath(strwholepath);
				if(null == entities){
					return true;
				}
				for(int i=0;i<entities.size();i++){
					FileUploadEntity entity  = entities.get(i);
					if(2 != entity.getFileState()){
						isLoadOver = false;
						break;
					}else{
						isLoadOver = true;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		for(int i=0;i<20;i++){
			Log.d("downserver","################### strwholepath:" + strwholepath + ",isLoadOver ? " + isLoadOver);
		}
		return isLoadOver;
	}
	
	/**
	 * 删除所有上传任务
	 */
	public void destoryAllTask(AllUploadTaskEntity allUploadTask){
		List<FileUploadEntity> fues = allUploadTask.getFileTasks();
		for(FileUploadEntity fue:fues){
			UploadThread ut = uploadThreads.get(fue.getWholePath());
			if(ut!=null && ut.isAlive()) ut.setFlag(true);// 暂停这个线程
		}
		Map<String,List<FileUploadEntity>> dirTasks = allUploadTask.getDirTasks();
		Set<Map.Entry<String,List<FileUploadEntity>>> dirTaskSet = dirTasks.entrySet();
		for(Map.Entry<String,List<FileUploadEntity>> enty:dirTaskSet){
			List<UploadThread> uts = dirUploadThreads.get(enty.getKey());
			if(uts!=null){
				for(UploadThread ut : uts){
					if(ut!=null && ut.isAlive()) ut.setFlag(true);// 暂停这个线程
				}
			}
		}
		fileUploadService.deleteAll();
	}
	
	//add by gaoge 2011-04-26
	/**
	 * 获得fileId对应的DownLoadThread对象
	 * 
	 * @param key
	 * @return
	 */
	public UploadThread getUploadThread(String key) {
		UploadThread ds = uploadThreads.get(key);
		return ds;
	}
	
	/**
	 * 获得dirId对应的DownLoadThread对象
	 * 
	 * @param key
	 * @return
	 */
	public List<UploadThread> getUploadDirThreads(String dirkey) {
		List<UploadThread> ds_list = dirUploadThreads.get(dirkey);
		return ds_list;
	}
	
	//add by gaoge 2011-04-27
	public String getParentRootPath(String filepath){
		return fileUploadService.getParentRootPath(filepath);
	}
}
